/**
 * 穴位相关数据类型定义
 * 基于实际API响应数据结构
 */

/**
 * 穴位类型枚举
 */
export enum AcupointType {
  /** 经络 */
  MERIDIAN = 'meridian',
  /** 穴位 */
  ACUPOINT = 'acupoint'
}

/**
 * 位置类型枚举
 */
export enum LocationType {
  /** 穴位 */
  ACUPOINT = 'acupoint'
}

/**
 * 侧位类型枚举
 */
export enum SideType {
  /** 单侧 */
  SINGLE = 'single',
  /** 双侧 */
  BILATERAL = 'bilateral',
  /** 无侧位 */
  NONE = ''
}

/**
 * 穴位信息接口
 */
export interface AcupointInfo {
  /** 穴位代码 */
  acupointCode: string;
  /** 穴位名称 */
  acupointText: string;
  /** 穴位拼音 */
  acupointPinyin: string;
  /** 穴位类型 */
  acupointType: AcupointType;
  /** 位置类型 */
  locationType: LocationType;
  /** 侧位类型 */
  sideType: SideType;
  /** 父级代码 */
  parentCode: string;
  /** 子穴位列表 */
  children: AcupointInfo[];
  /** ID */
  id: string;
  /** 父级ID */
  parentId: string;
}

/**
 * API响应数据结构
 */
export interface AcupointApiResponse {
  /** 响应代码 */
  code: string;
  /** 响应消息 */
  msg: string;
  /** 时间戳 */
  timestamp: number;
  /** 穴位数据 */
  data: AcupointInfo[];
  /** 是否成功 */
  ok: boolean;
}

/**
 * 穴位查询参数
 */
export interface AcupointQueryParams {
  /** 父级代码 */
  parentCode?: string;
  /** 穴位类型 */
  acupointType?: AcupointType;
  /** 关键词搜索 */
  keyword?: string;
  /** 页码 */
  page?: number;
  /** 每页大小 */
  pageSize?: number;
}

/**
 * 扁平化穴位信息（用于搜索和筛选）
 */
export interface FlatAcupointInfo extends AcupointInfo {
  /** 层级路径 */
  path: string[];
  /** 层级深度 */
  level: number;
}

/**
 * 获取穴位类型文本
 */
export const getAcupointTypeText = (type: AcupointType): string => {
  const typeMap: Record<AcupointType, string> = {
    [AcupointType.MERIDIAN]: '经络',
    [AcupointType.ACUPOINT]: '穴位'
  };
  return typeMap[type] || type;
};

/**
 * 获取侧位类型文本
 */
export const getSideTypeText = (type: SideType): string => {
  const typeMap: Record<string, string> = {
    [SideType.SINGLE]: '单侧',
    [SideType.BILATERAL]: '双侧',
    [SideType.NONE]: '无侧位'
  };
  return typeMap[type] || type;
};

/**
 * 扁平化穴位数据
 * @param acupoints 穴位树形数据
 * @param parentPath 父级路径
 * @param level 层级
 * @returns 扁平化的穴位数组
 */
export const flattenAcupoints = (
  acupoints: AcupointInfo[], 
  parentPath: string[] = [], 
  level: number = 0
): FlatAcupointInfo[] => {
  const result: FlatAcupointInfo[] = [];
  
  acupoints.forEach(acupoint => {
    const currentPath = [...parentPath, acupoint.acupointText];
    const flatItem: FlatAcupointInfo = {
      ...acupoint,
      path: currentPath,
      level
    };
    
    result.push(flatItem);
    
    // 递归处理子穴位
    if (acupoint.children && acupoint.children.length > 0) {
      result.push(...flattenAcupoints(acupoint.children, currentPath, level + 1));
    }
  });
  
  return result;
};

/**
 * 根据类型筛选穴位
 * @param acupoints 穴位数组
 * @param type 穴位类型
 * @returns 筛选后的穴位数组
 */
export const filterAcupointsByType = (
  acupoints: AcupointInfo[], 
  type: AcupointType
): AcupointInfo[] => {
  return acupoints.filter(acupoint => acupoint.acupointType === type);
};

/**
 * 搜索穴位
 * @param acupoints 穴位数组
 * @param keyword 搜索关键词
 * @returns 搜索结果
 */
export const searchAcupoints = (
  acupoints: AcupointInfo[], 
  keyword: string
): AcupointInfo[] => {
  if (!keyword.trim()) return acupoints;
  
  const lowerKeyword = keyword.toLowerCase();
  
  return acupoints.filter(acupoint => 
    acupoint.acupointText.toLowerCase().includes(lowerKeyword) ||
    acupoint.acupointCode.toLowerCase().includes(lowerKeyword) ||
    acupoint.acupointPinyin.toLowerCase().includes(lowerKeyword)
  );
};

/**
 * 根据代码查找穴位
 * @param acupoints 穴位数组
 * @param code 穴位代码
 * @returns 找到的穴位或undefined
 */
export const findAcupointByCode = (
  acupoints: AcupointInfo[], 
  code: string
): AcupointInfo | undefined => {
  for (const acupoint of acupoints) {
    if (acupoint.acupointCode === code) {
      return acupoint;
    }
    
    if (acupoint.children && acupoint.children.length > 0) {
      const found = findAcupointByCode(acupoint.children, code);
      if (found) return found;
    }
  }
  
  return undefined;
};

/**
 * 根据名称查找穴位
 * @param acupoints 穴位数组
 * @param name 穴位名称
 * @returns 找到的穴位或undefined
 */
export const findAcupointByName = (
  acupoints: AcupointInfo[], 
  name: string
): AcupointInfo | undefined => {
  for (const acupoint of acupoints) {
    if (acupoint.acupointText === name) {
      return acupoint;
    }
    
    if (acupoint.children && acupoint.children.length > 0) {
      const found = findAcupointByName(acupoint.children, name);
      if (found) return found;
    }
  }
  
  return undefined;
};

/**
 * 获取穴位路径
 * @param targetAcupoint 目标穴位
 * @param allAcupoints 所有穴位数据
 * @returns 穴位路径数组
 */
export const getAcupointPath = (
  targetAcupoint: AcupointInfo, 
  allAcupoints: AcupointInfo[]
): AcupointInfo[] => {
  const path: AcupointInfo[] = [];
  
  const findPath = (acupoints: AcupointInfo[], target: string): boolean => {
    for (const acupoint of acupoints) {
      path.push(acupoint);
      
      if (acupoint.acupointCode === target) {
        return true;
      }
      
      if (acupoint.children && acupoint.children.length > 0) {
        if (findPath(acupoint.children, target)) {
          return true;
        }
      }
      
      path.pop();
    }
    
    return false;
  };
  
  findPath(allAcupoints, targetAcupoint.acupointCode);
  return path;
};

/**
 * 获取经络类型的穴位
 * @param acupoints 穴位数组
 * @returns 经络类型的穴位数组
 */
export const getMeridianAcupoints = (acupoints: AcupointInfo[]): AcupointInfo[] => {
  return acupoints.filter(acupoint => acupoint.acupointType === AcupointType.MERIDIAN);
};

/**
 * 获取具体穴位（非经络）
 * @param acupoints 穴位数组
 * @returns 具体穴位数组
 */
export const getConcreteAcupoints = (acupoints: AcupointInfo[]): AcupointInfo[] => {
  return flattenAcupoints(acupoints).filter(acupoint => acupoint.acupointType === AcupointType.ACUPOINT);
};

/**
 * 统计穴位数量
 * @param acupoints 穴位数组
 * @returns 统计信息
 */
export const getAcupointStats = (acupoints: AcupointInfo[]) => {
  const flatAcupoints = flattenAcupoints(acupoints);
  
  return {
    total: flatAcupoints.length,
    meridians: flatAcupoints.filter(item => item.acupointType === AcupointType.MERIDIAN).length,
    acupoints: flatAcupoints.filter(item => item.acupointType === AcupointType.ACUPOINT).length,
    maxLevel: Math.max(...flatAcupoints.map(item => item.level))
  };
};
